package com.sdut.material.shiro;

import com.sdut.material.shiro.cache.RedisCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    // 将自己写的验证方式Realm加入Spring容器
    @Bean
    public CustomRealm customRealm() {
        CustomRealm customRealm = new CustomRealm();

        // Shiro结合EhCache实现的是本地缓存，本地缓存就是在应用内部的缓存，
        // 缺点就是重启后数据丢失
        //开启缓存管理器
        //customRealm.setCacheManager(new EhCacheManager());
        customRealm.setCacheManager(new RedisCacheManager());
        customRealm.setCachingEnabled(true);//开启全局缓存
        customRealm.setAuthenticationCachingEnabled(true);// 开启认证缓存
        customRealm.setAuthenticationCacheName("authenticationName");// 认证缓存名字
        customRealm.setAuthorizationCachingEnabled(true); //开启授权缓存
        customRealm.setAuthorizationCacheName("authorizationName");// 授权缓存名字

        return customRealm;
    }

    // @Bean注解相应的方法，该方法名默认就是Bean的名称，该方法返回值就是Bean的对象。
    // 去掉shiro登录时url里的JSESSIONID
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        // 去掉shiro登录时url里的JSESSIONID
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    //SecurityManager
    @Bean
    public SecurityManager getSecurityManager(CustomRealm customRealm, DefaultWebSessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 不建议这样使用，因为customRealm()返回的对象已经交给Spring来管理了
        // securityManager.setRealm(customRealm());
        securityManager.setRealm(customRealm);
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }



    //Filter工厂，设置SecurityManager，设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 添加shiro的内置过滤器
        // anon: 无需认证就可以访问
        // authc: 必须认证才能访问
        // user: 必须拥有"记住我"功能才能访问
        // perms: 拥有对某个资源的权限才能访问
        // role: 拥有某个角色才能访问

        Map<String, String> filterMap = new LinkedHashMap<>();
        // authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
        filterMap.put("/login", "anon");
        filterMap.put("/getLoginPage", "anon");
        filterMap.put("/static/**", "anon");
        filterMap.put("/static/layer", "anon");
        filterMap.put("/static/layui", "anon");
        filterMap.put("/static/layui_extends", "anon");
        filterMap.put("/getImage","anon");//验证码
        //对所有用户认证 【注意要放到下面，不然静态资源都会被拦截】
        filterMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        // 若没有登录，则被authc过滤器重定向到登录页面
        shiroFilterFactoryBean.setLoginUrl("/getLoginPage");

        return shiroFilterFactoryBean;
    }

}
